package it.tcm.TeacherClassMate.writer;

import it.tcm.TeacherClassMate.beans.EquationBean;
import it.tcm.TeacherClassMate.facade.EquationManageBase;
import it.tcm.TeacherClassMate.form.EquationUploadForm;
import it.tcm.TeacherClassMate.persistent.DBConnection;
import it.tcm.TeacherClassMate.util.DocxToHtmlMaker;
import it.tcm.TeacherClassMate.util.ResultToHtmlMaker;
import it.tcm.TeacherClassMate.util.Util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.log4j.Logger;


public class EquationBeanWriter {
	
	private String base = null;
	private JAXBContext contextObj = null;
	private Marshaller marshallerObj = null;
	
	
	private EquationBeanWriter(String base) {
		this.base = base;
		 try{		
		   contextObj = JAXBContext.newInstance(org.docx4j.math.CTOMathPara.class);
		   marshallerObj = contextObj.createMarshaller();
		   marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);	
		 } catch (Exception e) {
			 
		 }
	}
	
    private static volatile EquationBeanWriter instance = null;
	
	public static EquationBeanWriter getInstance(String base) {
        if (instance == null) {
                synchronized (EquationBeanWriter .class){
                        if (instance == null) {
                                instance = new EquationBeanWriter (base);
                        }
              }
        }
        return instance;
    }
	
	private Logger logger = Logger.getLogger(this.getClass().getName());
	
	public boolean insertEquation(EquationUploadForm form,boolean blobFlag,Integer typologyId)  {
	
	  Connection  conn = null;
	
	  try{		
	
		  DBConnection db = new DBConnection();
		  conn = db.getDBConnection();
		  		   
		  Context ctx = new InitialContext();
		  String docxFileDir = (String)ctx.lookup("java:comp/env/docxPath");
		  
		  EquationManageBase emb = new EquationManageBase();
		  
		  String equationDocxFileDir = docxFileDir + "//E//";
		  
		  // create directory if not
		  File dir = new File(equationDocxFileDir);
		  if (!dir.exists()) {
			  	new File(equationDocxFileDir).mkdir();
		  }	  
		     
	      EquationBean equationBean = new EquationBean();
	      equationBean.setTypologyId(typologyId);
	      equationBean.setType(Util.EQUATION);    
	      equationBean.setCoefficienti(form.getCoefficienti());
	      equationBean.setDifficolta(Integer.valueOf(form.getDifficolta()));
	      equationBean.setPrefix(Util.EQUATION_PREFIX);	     
	      equationBean.setEsponenziale(form.getEsponenziale());   
	      equationBean.setFormaNormale(form.getFormanormale());
	      equationBean.setSistema(form.getSistema());
	      equationBean.setFratta(form.getFratta());	   
	      equationBean.setGrado(Integer.valueOf(form.getGrado()));
	      equationBean.setIrrazionale(form.getIrrazionale() );
	      equationBean.setLogaritmica(form.getLogaritmica());
	      equationBean.setResultString(form.getResultstring());
	      emb.save(equationBean);
	      form.setId(equationBean.getId());
	
		  
		  String filedocxfilename = equationDocxFileDir + Util.EQUATION_PREFIX + equationBean.getId().toString() + ".docx";
		  logger.info("filedocxfilename " + equationDocxFileDir + Util.EQUATION_PREFIX + equationBean.getId().toString() + ".docx");	
		  String filehtmfilename = equationDocxFileDir + Util.EQUATION_PREFIX + equationBean.getId().toString() + ".htm";
		  logger.info("filehtmfilename " + equationDocxFileDir + Util.EQUATION_PREFIX + equationBean.getId().toString() + ".htm");	
		  File filedocx = Util.bytesToFile(filedocxfilename, form.getDocx().getFileData());
		  logger.info("form.getDocx().getFileSize() " + form.getDocx().getFileSize());	
		  File filehtm = DocxToHtmlMaker.getDocxToHtmlMaker().make(marshallerObj, filedocx, filedocxfilename, filehtmfilename, equationDocxFileDir,equationBean.getId().toString(),base);
		  File fileresult = null;
		  File fileresulthtm = null;
		  String fileresultdocxfilename = equationDocxFileDir + Util.EQUATION_PREFIX + equationBean.getId().toString() + "_result.docx";
		  String fileresulthtmfilename = equationDocxFileDir + Util.EQUATION_PREFIX + equationBean.getId().toString() + "_result.htm";  
		  if ( equationBean.getResultString() == null || equationBean.getResultString().trim().equals("")) {		  
			  logger.info("form.getResult().getFileSize() " + form.getResult().getFileSize());				
			  fileresult = Util.bytesToFile(fileresultdocxfilename, form.getResult().getFileData());
			  fileresulthtm = DocxToHtmlMaker.getDocxToHtmlMaker().make(marshallerObj, fileresult, fileresultdocxfilename, fileresulthtmfilename, equationDocxFileDir,equationBean.getId().toString(),base);		
		  } else {
			  // creo file per il risultato
			  ResultToHtmlMaker resultmaker = new ResultToHtmlMaker();
			  fileresult = resultmaker.create(equationBean.getResultString(), fileresult, fileresultdocxfilename);
			  fileresulthtm = resultmaker.make(fileresult,fileresulthtmfilename);
		  }
		  if (blobFlag) {
	
			    String sql = "UPDATE EQUATION SET docx = ?, image = ?, result = ?, result_image = ? WHERE id = ?";
			    PreparedStatement stmt0 = conn.prepareStatement(sql);
			    
			    stmt0.setInt(5, equationBean.getId());
			    	
			    logger.info("filedocxoutput.length()" + filedocx.length());
			    FileInputStream fisdocx = new FileInputStream(filedocx);	    		    	   
			    stmt0.setBinaryStream(1, fisdocx, (int) filedocx.length()); // metto il docx	
			    
			    logger.info("image.length()" + filehtm.length());
			    FileInputStream fisimage = new FileInputStream(filehtm);	    		    	   
			    stmt0.setBinaryStream(2, fisimage, (int) filehtm.length()); // metto html del docx
			    
			    logger.info("fileresult.length()" + fileresult.length());
			    FileInputStream fisresult = new FileInputStream(fileresult);	    		    	   
			    stmt0.setBinaryStream(3, fisresult, (int) fileresult.length()); // metto il result	
			    
			    logger.info("result_image.length()" + fileresulthtm.length());
			    FileInputStream fisresult_image = new FileInputStream(fileresulthtm);	    		    	   
			    stmt0.setBinaryStream(4, fisresult_image, (int) fileresulthtm.length()); // metto html del result
			    		    
			    stmt0.execute();				    
			    fisdocx.close();
			    fisimage.close();
			    fisresult.close();
			    fisresult_image.close();
    
		  }
		    
	  } catch (Throwable e) {
		    logger.error("Exception " + e.getMessage());  
		    e.printStackTrace();
		    return false;
	  } finally {
		  try {
			    conn.close();
		  } catch (SQLException e) {
			  e.printStackTrace();
	      }
	 }
	  
	 return true;
	  
   }
	

   public File simpleTransformer(String XML, String outputFile, String XSLT) {
		  final ArrayList<String> errorList = new ArrayList<String>();
		  File fileout  = null;
		  try {
	            // Set transformer to SAXON
	            System.setProperty("javax.xml.transform.TransformerFactory","net.sf.saxon.TransformerFactoryImpl");
	            // Set up input documents
	            Source inputXML = new StreamSource(new File(XML));
	            Source inputXSL = new StreamSource(new File(XSLT));
	            
	            fileout = new File(outputFile);

	            // Set up output sink
	            StreamResult outputXHTML = new StreamResult(fileout);

	            // Setup a factory for transforms
	            TransformerFactory factory = TransformerFactory.newInstance();

	            // Precompile the XSL into a Templates object
	            Templates templates = factory.newTemplates(inputXSL);

	            // Get a Transformer from the Templates
	            Transformer transformer = templates.newTransformer();
	            ErrorListener listener = new ErrorListener() {

	                public void error(TransformerException exception) throws TransformerException {
	                    errorList.add(exception.getMessage());
	                }

	                public void fatalError(TransformerException exception) throws TransformerException {
	                    errorList.add(exception.getMessage());
	                    throw exception;
	                }

	                public void warning(TransformerException exception) throws TransformerException {
	                    errorList.add(exception.getMessage());
	                }
	            };
	            System.out.println("There were " + errorList.size() + "errors.");
	            transformer.setErrorListener(listener);

	            // Perform the transformation
	            transformer.transform(inputXML, outputXHTML);
	            logger.info("trasformed");
	   

	        } catch (TransformerConfigurationException e) {
	            errorList.add("The underlying XSL processor " + "does not support the requested features.\n" + e.getMessage());

	        } catch (TransformerException e) {
	            errorList.add("Error occurred obtaining " + "XSL processor.\n" + e.getMessage());
	           
	        } 
		  
		    return fileout;
		  
	    } 
	
	public static void saveStringToFile(String contents, String filename) throws IOException {  
		  PrintWriter out = new PrintWriter(new FileWriter(filename));  
		  out.print(contents);  
		  out.close();  
		}  


}
